import * as THREE from 'three';
import type { CollisionResult } from './collisionDetector';

// 调试配置接口
export interface DebugConfig {
  showBoundingBoxes: boolean;
  showCollisionPoints: boolean;
  showCollisionNormals: boolean;
  showSpatialGrid: boolean;
  boundingBoxColor: number;
  collisionPointColor: number;
  normalColor: number;
  gridColor: number;
  normalLength: number;
}

// 调试统计接口
export interface CollisionStats {
  totalCollisions: number;
  currentCollisions: number;
  lastCollisionTime: number;
  averageCollisionsPerSecond: number;
  maxPenetrationDepth: number;
}

/**
 * 碰撞调试器
 * 提供碰撞系统的可视化调试功能
 */
export class CollisionDebugger {
  private scene: THREE.Scene;
  private config: DebugConfig;
  private stats: CollisionStats;
  
  // 调试视觉元素
  private boundingBoxHelpers: Map<THREE.Object3D, THREE.BoxHelper> = new Map();
  private collisionPointMarkers: THREE.Group = new THREE.Group();
  private normalArrows: THREE.Group = new THREE.Group();
  private spatialGridLines: THREE.Group = new THREE.Group();
  private carBoundingBoxHelper: THREE.BoxHelper | null = null;
  
  // 统计计算
  private collisionHistory: number[] = [];
  private historyWindow: number = 60; // 1秒的历史记录（60fps）
  
  constructor(scene: THREE.Scene, config?: Partial<DebugConfig>) {
    this.scene = scene;
    
    this.config = {
      showBoundingBoxes: true,
      showCollisionPoints: true,
      showCollisionNormals: true,
      showSpatialGrid: false,
      boundingBoxColor: 0x00ff00,
      collisionPointColor: 0xff0000,
      normalColor: 0x0000ff,
      gridColor: 0x888888,
      normalLength: 2.0,
      ...config
    };
    
    this.stats = {
      totalCollisions: 0,
      currentCollisions: 0,
      lastCollisionTime: 0,
      averageCollisionsPerSecond: 0,
      maxPenetrationDepth: 0
    };
    
    this.initDebugGroups();
  }

  /**
   * 初始化调试组
   */
  private initDebugGroups(): void {
    this.collisionPointMarkers.name = 'CollisionPointMarkers';
    this.normalArrows.name = 'NormalArrows';
    this.spatialGridLines.name = 'SpatialGridLines';
    
    this.scene.add(this.collisionPointMarkers);
    this.scene.add(this.normalArrows);
    this.scene.add(this.spatialGridLines);
  }

  /**
   * 更新调试显示
   * @param buildingBounds 建筑物边界框映射
   * @param carBounds 车辆边界框
   * @param collisions 当前碰撞结果
   * @param gridSize 空间网格大小
   */
  public update(
    buildingBounds: Map<THREE.Object3D, THREE.Box3>,
    carBounds: THREE.Box3,
    collisions: CollisionResult[],
    gridSize?: number
  ): void {
    // 更新统计信息
    this.updateStats(collisions);
    
    // 更新建筑物边界框显示
    if (this.config.showBoundingBoxes) {
      this.updateBuildingBoundingBoxes(buildingBounds);
      this.updateCarBoundingBox(carBounds);
    } else {
      this.hideBoundingBoxes();
    }
    
    // 更新碰撞点和法向量显示
    if (this.config.showCollisionPoints || this.config.showCollisionNormals) {
      this.updateCollisionVisualization(collisions);
    } else {
      this.hideCollisionVisualization();
    }
    
    // 更新空间网格显示
    if (this.config.showSpatialGrid && gridSize) {
      this.updateSpatialGrid(gridSize);
    } else {
      this.hideSpatialGrid();
    }
  }

  /**
   * 更新统计信息
   * @param collisions 当前碰撞结果
   */
  private updateStats(collisions: CollisionResult[]): void {
    const currentTime = Date.now();
    
    // 更新当前碰撞数
    this.stats.currentCollisions = collisions.length;
    
    // 更新总碰撞数
    if (collisions.length > 0) {
      this.stats.totalCollisions += collisions.length;
      this.stats.lastCollisionTime = currentTime;
      
      // 更新最大穿透深度
      collisions.forEach(collision => {
        if (collision.penetrationDepth && collision.penetrationDepth > this.stats.maxPenetrationDepth) {
          this.stats.maxPenetrationDepth = collision.penetrationDepth;
        }
      });
    }
    
    // 更新碰撞历史
    this.collisionHistory.push(collisions.length);
    if (this.collisionHistory.length > this.historyWindow) {
      this.collisionHistory.shift();
    }
    
    // 计算平均碰撞频率
    const totalCollisionsInWindow = this.collisionHistory.reduce((sum, count) => sum + count, 0);
    this.stats.averageCollisionsPerSecond = totalCollisionsInWindow / (this.historyWindow / 60);
  }

  /**
   * 更新建筑物边界框显示
   * @param buildingBounds 建筑物边界框映射
   */
  private updateBuildingBoundingBoxes(buildingBounds: Map<THREE.Object3D, THREE.Box3>): void {
    // 移除不存在的边界框
    for (const [building, helper] of this.boundingBoxHelpers) {
      if (!buildingBounds.has(building)) {
        this.scene.remove(helper);
        this.boundingBoxHelpers.delete(building);
      }
    }
    
    // 添加或更新边界框
    for (const [building, bounds] of buildingBounds) {
      let helper = this.boundingBoxHelpers.get(building);
      
      if (!helper) {
        // 创建新的边界框辅助器
        const tempBox = new THREE.Mesh(new THREE.BoxGeometry(), new THREE.MeshBasicMaterial());
        helper = new THREE.BoxHelper(tempBox, this.config.boundingBoxColor);
        this.boundingBoxHelpers.set(building, helper);
        this.scene.add(helper);
      }
      
      // 更新边界框位置和大小
      this.updateBoxHelper(helper, bounds);
    }
  }

  /**
   * 更新车辆边界框显示
   * @param carBounds 车辆边界框
   */
  private updateCarBoundingBox(carBounds: THREE.Box3): void {
    if (!this.carBoundingBoxHelper) {
      const tempBox = new THREE.Mesh(new THREE.BoxGeometry(), new THREE.MeshBasicMaterial());
      this.carBoundingBoxHelper = new THREE.BoxHelper(tempBox, 0xffff00); // 黄色
      this.scene.add(this.carBoundingBoxHelper);
    }
    
    this.updateBoxHelper(this.carBoundingBoxHelper, carBounds);
  }

  /**
   * 更新边界框辅助器
   * @param helper 边界框辅助器
   * @param bounds 边界框
   */
  private updateBoxHelper(helper: THREE.BoxHelper, bounds: THREE.Box3): void {
    const center = bounds.getCenter(new THREE.Vector3());
    const size = bounds.getSize(new THREE.Vector3());
    
    // 更新辅助器的变换矩阵
    helper.position.copy(center);
    helper.scale.copy(size);
    helper.updateMatrix();
  }

  /**
   * 隐藏边界框
   */
  private hideBoundingBoxes(): void {
    for (const helper of this.boundingBoxHelpers.values()) {
      this.scene.remove(helper);
    }
    this.boundingBoxHelpers.clear();
    
    if (this.carBoundingBoxHelper) {
      this.scene.remove(this.carBoundingBoxHelper);
      this.carBoundingBoxHelper = null;
    }
  }

  /**
   * 更新碰撞可视化
   * @param collisions 碰撞结果数组
   */
  private updateCollisionVisualization(collisions: CollisionResult[]): void {
    // 清除之前的可视化
    this.clearGroup(this.collisionPointMarkers);
    this.clearGroup(this.normalArrows);
    
    collisions.forEach((collision, index) => {
      if (!collision.contactPoint) return;
      
      // 显示碰撞点
      if (this.config.showCollisionPoints) {
        const pointGeometry = new THREE.SphereGeometry(0.1, 8, 8);
        const pointMaterial = new THREE.MeshBasicMaterial({ 
          color: this.config.collisionPointColor 
        });
        const pointMarker = new THREE.Mesh(pointGeometry, pointMaterial);
        pointMarker.position.copy(collision.contactPoint);
        this.collisionPointMarkers.add(pointMarker);
      }
      
      // 显示碰撞法向量
      if (this.config.showCollisionNormals && collision.normal) {
        const arrowHelper = new THREE.ArrowHelper(
          collision.normal,
          collision.contactPoint,
          this.config.normalLength,
          this.config.normalColor
        );
        this.normalArrows.add(arrowHelper);
      }
    });
  }

  /**
   * 隐藏碰撞可视化
   */
  private hideCollisionVisualization(): void {
    this.clearGroup(this.collisionPointMarkers);
    this.clearGroup(this.normalArrows);
  }

  /**
   * 更新空间网格显示
   * @param gridSize 网格大小
   */
  private updateSpatialGrid(gridSize: number): void {
    this.clearGroup(this.spatialGridLines);
    
    const gridRange = 50; // 显示范围
    const gridMaterial = new THREE.LineBasicMaterial({ 
      color: this.config.gridColor,
      transparent: true,
      opacity: 0.3
    });
    
    // 创建网格线
    for (let x = -gridRange; x <= gridRange; x += gridSize) {
      // 垂直线
      const vPoints = [
        new THREE.Vector3(x, 0, -gridRange),
        new THREE.Vector3(x, 0, gridRange)
      ];
      const vGeometry = new THREE.BufferGeometry().setFromPoints(vPoints);
      const vLine = new THREE.Line(vGeometry, gridMaterial);
      this.spatialGridLines.add(vLine);
    }
    
    for (let z = -gridRange; z <= gridRange; z += gridSize) {
      // 水平线
      const hPoints = [
        new THREE.Vector3(-gridRange, 0, z),
        new THREE.Vector3(gridRange, 0, z)
      ];
      const hGeometry = new THREE.BufferGeometry().setFromPoints(hPoints);
      const hLine = new THREE.Line(hGeometry, gridMaterial);
      this.spatialGridLines.add(hLine);
    }
  }

  /**
   * 隐藏空间网格
   */
  private hideSpatialGrid(): void {
    this.clearGroup(this.spatialGridLines);
  }

  /**
   * 清除组中的所有对象
   * @param group 要清除的组
   */
  private clearGroup(group: THREE.Group): void {
    while (group.children.length > 0) {
      const child = group.children[0];
      group.remove(child);
      
      // 清理几何体和材质
      if (child instanceof THREE.Mesh) {
        child.geometry.dispose();
        if (Array.isArray(child.material)) {
          child.material.forEach(material => material.dispose());
        } else {
          child.material.dispose();
        }
      }
    }
  }

  /**
   * 更新配置
   * @param newConfig 新配置
   */
  public updateConfig(newConfig: Partial<DebugConfig>): void {
    this.config = { ...this.config, ...newConfig };
  }

  /**
   * 获取当前配置
   * @returns 当前配置
   */
  public getConfig(): DebugConfig {
    return { ...this.config };
  }

  /**
   * 获取统计信息
   * @returns 统计信息
   */
  public getStats(): CollisionStats {
    return { ...this.stats };
  }

  /**
   * 重置统计信息
   */
  public resetStats(): void {
    this.stats = {
      totalCollisions: 0,
      currentCollisions: 0,
      lastCollisionTime: 0,
      averageCollisionsPerSecond: 0,
      maxPenetrationDepth: 0
    };
    this.collisionHistory = [];
  }

  /**
   * 设置可见性
   * @param visible 是否可见
   */
  public setVisible(visible: boolean): void {
    this.collisionPointMarkers.visible = visible;
    this.normalArrows.visible = visible;
    this.spatialGridLines.visible = visible;
    
    for (const helper of this.boundingBoxHelpers.values()) {
      helper.visible = visible;
    }
    
    if (this.carBoundingBoxHelper) {
      this.carBoundingBoxHelper.visible = visible;
    }
  }

  /**
   * 清理资源
   */
  public dispose(): void {
    this.hideBoundingBoxes();
    this.hideCollisionVisualization();
    this.hideSpatialGrid();
    
    this.scene.remove(this.collisionPointMarkers);
    this.scene.remove(this.normalArrows);
    this.scene.remove(this.spatialGridLines);
  }
}